#![allow(unused_imports, non_snake_case, non_camel_case_types, unused_variables)]
use super::windows::*;
use super::*;

pub unsafe fn get_font_name_en(font: &mut ComPtr<IDWriteFont>) -> Option<String> {
	let mut names: *mut IDWriteLocalizedStrings = ptr::null_mut();
	if S_OK != font.GetFaceNames(&mut names) {
		return None;
	}
	let mut names = ComPtr::from_raw(names);
	get_locale_string_en(&mut names)
}
pub unsafe fn get_family_name_en(family: &mut ComPtr<IDWriteFontFamily>) -> Option<String> {
	let mut names: *mut IDWriteLocalizedStrings = ptr::null_mut();
	if S_OK != family.GetFamilyNames(&mut names) {
		return None;
	}
	let mut names = ComPtr::from_raw(names);
	get_locale_string_en(&mut names)
}
pub unsafe fn get_locale_string_en(strings: &mut ComPtr<IDWriteLocalizedStrings>) -> Option<String> {
	thread_local! {
		static EN_US_LOCALE: std::rc::Rc<Vec<wchar_t>> = std::rc::Rc::new(OsStr::new("en-us").to_wide_null());
	}
	let mut index: u32 = 0;
	let mut exists: BOOL = FALSE;
	let hr = strings.FindLocaleName((EN_US_LOCALE.with(|v| v.clone())).as_ptr(), &mut index, &mut exists);
	if hr != S_OK || exists == FALSE {
		// Ultimately fall back to first locale on list
		index = 0;
	}
	get_locale_string(strings, index)
}
pub unsafe fn get_locale_string(strings: &mut ComPtr<IDWriteLocalizedStrings>, index: UINT32) -> Option<String> {
	let mut buffer = [0u16; 1024];
	let mut length: UINT32 = 0;
	if S_OK != strings.GetStringLength(index, &mut length) {
		return None;
	}
	if length + 1 > buffer.len() as _ {
		return Default::default();
	}
	if S_OK != strings.GetString(index, buffer.as_mut_ptr(), length + 1) {
		return None;
	}
	String::from_utf16(&buffer[..length as _]).ok()
}
pub unsafe fn font_file(font: &mut ComPtr<IDWriteFont>) -> Option<(u32, PathBuf)> {
	let mut face: *mut IDWriteFontFace = ptr::null_mut();
	if S_OK != font.CreateFontFace(&mut face) {
		return None;
	}
	let Some(face) = ComPtr::try_from_raw(face) else { return None };

	let mut num_files: UINT32 = 0;
	if S_OK != face.GetFiles(&mut num_files, ptr::null_mut()) {
		return None;
	}
	if num_files < 1 {
		return None;
	}
	num_files = 1;
	let mut file: *mut IDWriteFontFile = ptr::null_mut();
	if S_OK != face.GetFiles(&mut num_files, &mut file) {
		return None;
	}
	let path = font_file_path(&mut ComPtr::from_raw(file))?;
	let index = face.GetIndex();
	Some((index, path))
}
#[cfg(target_os = "windows")]
pub unsafe fn font_file_path(fontfile: &mut ComPtr<IDWriteFontFile>) -> Option<PathBuf> {
	use std::os::windows::ffi::OsStringExt as _;
	let mut loader: *mut IDWriteFontFileLoader = ptr::null_mut();
	if S_OK != fontfile.GetLoader(&mut loader) {
		return None;
	}
	let loader = ComPtr::try_from_raw(loader)?;

	let mut ref_key: *const c_void = ptr::null();
	let mut ref_size: UINT32 = 0;
	if S_OK != fontfile.GetReferenceKey(&mut ref_key, &mut ref_size) {
		return None;
	}

	let loader: ComPtr<IDWriteLocalFontFileLoader> = loader.cast().ok()?;

	let mut path = [0u16; 1024];
	let mut length: UINT32 = 0;
	if S_OK != loader.GetFilePathLengthFromKey(ref_key, ref_size, &mut length) {
		return None;
	}
	if length + 1 > path.len() as _ {
		return None;
	}
	if S_OK != loader.GetFilePathFromKey(ref_key, ref_size, path.as_mut_ptr(), length + 1) {
		return None;
	}
	let path = &path[..length as _];
	Some(PathBuf::from(OsString::from_wide(&path)))
}
#[cfg(not(target_os = "windows"))]
pub unsafe fn font_file_path(fontfile: &mut ComPtr<IDWriteFontFile>) -> Option<PathBuf> {
	None
}
